using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DevExpress.Data.Utils;
using DevExpress.Xpf.Bars;
using DevExpress.Xpf.Data;
using Prism.Commands;
using Prism.Mvvm;
using RFS.BizLogic.PaiShi;
using RFS.BizLogic.PaiShi.Accounting;
using RFS.BizLogic.PaiShi.Ports.Adapters;
using RFS.BizLogic.utils;
using RFS.Domain.PaiShi;
using RFS.Domain.PaiShi.Accounting;
using RFS.Domain.PaiShi.WorkFlow;
using RFS.Domain.Sys;
using RFS.WPF.utils;
using RFS.WPF.Views.Settings;
using RFS.WPF.Views.Settings.HolidayPlan;
using ycx;
using MenuItem = RFS.Domain.Sys.MenuItem;

namespace RFS.WPF.Views
{
    public class VoucherSetWrapperVm : BindableBase
    {


        #region ShowGridDetails

        private bool _ShowGridDetails=false;

        public bool ShowGridDetails
        {
            get { return _ShowGridDetails; }
            set
            {
                _ShowGridDetails = value;
                RaisePropertyChanged(nameof(ShowGridDetails));
                RaisePropertyChanged(nameof(ShowGridSummary));
            }
        }
        public bool ShowGridSummary
        {
            get => !_ShowGridDetails;
        }

        #endregion

        private readonly IConfigT _config;

        public VoucherSetWrapperVm(IConfigT config, ILog log, IWorkFlowManager workFlowManager , IAccountingVoucherManager voucherManager)
        {

            Perio = new AccountPeriod(DateTime.Today.AddDays(-3), 1);

            _config = config;
            _log = log;
            _workFlowManager = workFlowManager;
            _voucherManager = voucherManager;

            ShowGridDetails = _config.ConfigSys.ShowGridDetails;
            //create the set
            _log.NewLogAdded += LogOnNewLogAdded;


            CmdProccesDefferences = new DelegateCommand (DoCmdProccesDefferences);
            CmdCheckAndCreateVouchers = new DelegateCommand (DoCmdCheckAndCreateVouchers);
            CmdManualyComplement = new DelegateCommand<string>(DoCmdManualyComplement);
            CmdCloseVoucher = new DelegateCommand(DoCmdCloseVoucher);
            CmdClearLogs = new DelegateCommand(DoCmdClearLogs);
            CmdLoadData = new DelegateCommand(DoCmdLoadData);
            CmdCheckBalance = new DelegateCommand(DoCmdCheckBalance);
            CopyVoucherToCopyclipbord = new DelegateCommand(DoCopyVoucherToCopyclipbord,()=>CurrentVoucher!=null );


            _cmds = GetAllCommands(this)
                .Where(x => x is DelegateCommand)
                .Select(x => x as DelegateCommand);


            InitAsync().Wait(1000);

            
        }

        private void DoCmdProccesDefferences()
        {
            _voucherSet.GotoDefferenceProcess( );
            
        }

        private void DoCopyVoucherToCopyclipbord()
        {
            var v = CurrentVoucher;
            if (v == null)
            {
                throw new Exception("当前凭证为空");
            }


            var sb = new StringBuilder();
            sb.AppendLine($"日期\t摘要\t供方数量\t供方金额\t收方数量\t收方金额");
            foreach (var itt in v.AccItems)
            {
                sb.AppendLine($"{itt.DO.RelatedOrderItem.BizTime:MM-dd}\t{itt.Remark}\t{itt.DO.AmountDebit.Quantity}\t{itt.DO.AmountDebit.AmountCash}\t {itt.DO.AmountCredit .Quantity}\t {itt.DO.AmountCredit.AmountCash}");
            }
            sb.AppendLine("");
            sb.AppendLine(
                $" \t 合计：  \t{v.DebitTotal.Quantity}\t{v.DebitTotal.AmountCash}\t {v.CreditTotal.Quantity}\t {v.CreditTotal.AmountCash}");

            sb.AppendLine("");
            sb.AppendLine($" \t \t量差：\t{v.DO.Balance.Quantity } \t额差：\t{v.DO.Balance.AmountCash}");


            
            sb.ToString().ToClipboard();
            _log.Info($"[{v.Id}]已复制成功");
        }

        private void DoCmdCheckAndCreateVouchers()
        {
            _showonlyBadRecords = true;
            
            _voucherSet.CheckToCreateAVs(true);
            
            _log.Info("完成对账");
            RaisePropertyChangedUI(nameof(ShowonlyBadRecords));
        }



        #region VState

        private VoucherSetState _VState;

        public VoucherSetState VState
        {
            get { return _VState; }
            set
            {
                _VState = value;
                IsPreparingData = value == VoucherSetState.准备;
                IsProcessDeferences = value != VoucherSetState.准备;
                RaisePropertyChanged(nameof(VState));
            }
        }

        #endregion
        
        
        // bool IsPreparing

        #region IsPreparingData

        private bool _isPreparingData=true ;

        public bool IsPreparingData
        {
            get { return _isPreparingData; }
            set
            {
                _isPreparingData = value;
                RaisePropertyChanged(nameof(IsPreparingData));
            }
        }

        #endregion

        #region IsProcessDeferences

        private bool _isProcessDeferences;

        public bool IsProcessDeferences
        {
            get { return _isProcessDeferences; }
            set
            {
                _isProcessDeferences = value;
                RaisePropertyChanged(nameof(IsProcessDeferences));
            }
        }

        #endregion

        private void DoCmdCloseVoucher()
        {

            ShowPopVoucher = false;
        }


        private IDayBasedWorkFlowNodeAccountingVoucherSetWrapper _voucherSet  ;
        public IDayBasedWorkFlowNodeAccountingVoucherSetWrapper DO {get { return _voucherSet; }}  
        private void DoCmdManualyComplement(string bizid)
        {
             $"请先进行【差异处理】".Required(this.VState== VoucherSetState.差异处理);
            //1 getMy voucher 
             // var av=_voucherSet.GetMyVoucherByLeftOrderId( bizid  );
             
             var lo=LeftSet.FirstOrDefault(x=>x.BizId==bizid);
             var av=_voucherSet.GetMyVoucherByOrder(lo);
             
             
             if (av == null)
             {
                 var ord= LeftSet.FirstOrDefault(x=>x.BizId==bizid);
                 // av=_voucherManager.CreateAV(ord,null );
                 av=_voucherSet.CreateAV(ord,null  );
                 av.VType = VType.手动制单;
                 _voucherSet.OnChangedNow();

             }

             SelectVoucher(av); 
             
            ShowPopVoucher = true ;

            // CurrentVoucher.Name = bizid;
            RaisePropertyChangedUI(nameof(CurrentVoucher));
        }

        private void SelectVoucher(IOrderItemBasedAccountingVoucher av)
        {
             CurrentVoucher= Vouchers.FirstOrDefault(x=> x.Id==av.Id);
        }


        #region CurrentVoucher




        private AccountVoucherVm _currentVoucher ;

        public AccountVoucherVm CurrentVoucher
        {
            get { return _currentVoucher; }
            set
            {
                _currentVoucher = value;
                RaisePropertyChangedUI(nameof(CurrentVoucher));
                NoteCommandsState();
            }
        }

        #endregion
        
        #region ShowPopVoucher

        private bool _showPopVoucher;

        public bool ShowPopVoucher
        {
            get { return _showPopVoucher; }
            set
            {
                _showPopVoucher = value;
                RaisePropertyChanged(nameof(ShowPopVoucher));
            }
        }

        #endregion

        private void DoCmdClearLogs()
        {
            Logs = "";
        }


        private int idxl = 0;

        private void LogOnNewLogAdded(object sender, string e)
        {
            Logs = $"{++idxl} {e}\n{Logs}";
        }

        private void DoCmdLoadData()
        {
            _voucherSet.GotoPreparingData();
            _log.Info($"系统加载数据中...");
            ShowonlyBadRecords = false;

            Cursorc= Cursors.Wait;
            
             Task.Run(async () =>
            {
                try
                {

                    _voucherSet.AccPeriod = Perio;

                    await _voucherSet.LoadLeftNodeDataAsync();
                    await _voucherSet.LoadRightNodeDataAsync(IncludeFromProductionLine, IncludeFromRegroup);

                    _log.Info($"载数据【{Perio}】完成");
                    // Cursorc= Cursors.Arrow;


                }
                catch (Exception e)
                {
                    // Cursorc= Cursors.Arrow;

                    Console.WriteLine(e);
                    _log.Err(e);
                }
                finally
                {
                    Cursorc= Cursors.Arrow;

                }

                 
                // _log.Info($"...");

            });
            
 

        }

        private void DoCmdCheckBalance()
        {
            // RunLongTask(() => _wnFH.CheckWith(_wnYS));
           RunLongTask(()=>   DoCmdCheckAndCreateVouchers() ); 
            
        }

        private async Task InitAsync()
        {
            await Task.Run(() =>
            {

       
                var avs= _voucherManager.GetDayBasedVoucherSet(Perio);
                if (avs == null)
                {
                    avs =_voucherManager.CreateAVs() ;
                }
                
                _voucherSet = avs ;
                _voucherSet.Changed += VoucherSetOnChanged;
                _voucherSet.SourceDataLoaded += VoucherSetOnSourceDataLoaded; 
                
            });
        }

        private void VoucherSetOnSourceDataLoaded(object sender, EventArgs e)
        {
            
            // RunLongTask(() =>
            // {
                var dsf = _voucherSet.LeftNode.WorkFlowNode.OrderItems;
                var dsy = _voucherSet.RightNode.WorkFlowNode.OrderItems;
               
                
                if (ShowonlyBadRecords  )
                {
                    dsf =  dsf.Where(x => !x.IsChecked).ToList();
                    dsy = dsy.Where(x => !x.IsChecked).ToList();
                }
      
                FhTitle = $"{_voucherSet.LeftNode }";
                YsTitle = $"{_voucherSet.RightNode }";
                CeTitle = $"量差：{_voucherSet.RightNode.DateItems.Sum(x=>x.Quantity)- _voucherSet.LeftNode.DateItems.Sum(x=>x.Quantity)  }";
      
                LeftSet = new ObservableCollection<IOrderItem>( );
                RightSet = new ObservableCollection<IOrderItem>( );   
                  
                LeftSet = new ObservableCollection<IOrderItem>(dsf);
                RightSet = new ObservableCollection<IOrderItem>(dsy);              
                
            // });

            
        }

        private void VoucherSetOnChanged(object sender, EventArgs e)
        {
            
            var res= 
                _voucherSet.Vouchers
                   
                    .Select(x=>new AccountVoucherVm(x,_config,_voucherSet, _voucherManager  ) );

            var old = CurrentVoucher;
            Vouchers = new ObservableCollection<AccountVoucherVm>(res);
            VState = _voucherSet.State;
            if (old!=null) SelectVoucher(old.DO);
            

            NoteCommandsState();
        }


        public List<ICommand> GetAllCommands(object viewModel)
        {
            var commands = new List<ICommand>();

            // Get all properties of the view model
            PropertyInfo[] properties = viewModel.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);

            // Iterate through properties
            foreach (PropertyInfo property in properties)
            {
                // Check if the property type is ICommand
                if (typeof(ICommand).IsAssignableFrom(property.PropertyType))
                {
                    // Get the value of the property (the command)
                    ICommand command = (ICommand)property.GetValue(viewModel);

                    // Add the command to the list
                    commands.Add(command);
                }
            }

            return commands;
        }

        public DelegateCommand<string> CmdManualyComplement { get; set; }
        public DelegateCommand CmdCloseVoucher { get; set; }
        public DelegateCommand CmdLoadData { get; set; }
        public DelegateCommand CmdClearLogs { get; set; }
        public DelegateCommand CmdCheckBalance { get; set; }
        public DelegateCommand CmdProccesDefferences { get; set; }
        public DelegateCommand CopyVoucherToCopyclipbord { get; set; }

        IEnumerable<DelegateCommand> _cmds = new List<DelegateCommand>();

        void NoteCommandsState()
        {
            foreach (var d in _cmds)
            {
                d.RaiseCanExecuteChanged();
            }
        }


        void NoteAllSet()
        {
            RaisePropertyChangedUI("LeftSet");
            RaisePropertyChangedUI("RightSet");
        }

        private ILog _log;

        #region Logs

        private string _logs;

        public string Logs
        {
            get { return _logs; }
            set
            {
                _logs = value;
                RaisePropertyChanged(nameof(Logs));
            }
        }

        #endregion


        #region ShowonlyBadRecords

        private bool _showonlyBadRecords;

        public bool ShowonlyBadRecords
        {
            get { return _showonlyBadRecords; }
            set
            {
                if (_showonlyBadRecords == value) return;
                _showonlyBadRecords = value;
                RaisePropertyChanged(nameof(ShowonlyBadRecords));

                Task.Run(() => VoucherSetOnSourceDataLoaded(null, null));

            }
        }

        #endregion


        #region Date

        private DateTime _date;

        public DateTime Date
        {
            get { return Perio.BeginDate; }
            set
            {
                Perio  =new AccountPeriod(value,1 ) ;
                RaisePropertyChanged(nameof(Date));
            }
        }

        #endregion

        private IWorkFlowManager _workFlowManager;


        private IWorkFlowNodeWrapper _wnFH;
        private IWorkFlowNodeWrapper _wnYS;

 

        #region fhTitle

        private string _fhTitle;

        public string FhTitle
        {
            get { return _fhTitle; }
            set
            {
                _fhTitle = value;
                RaisePropertyChanged(nameof(FhTitle));
            }
        }

        #endregion

        #region ysTitle

        private string _ysTitle;

        public string YsTitle
        {
            get { return _ysTitle; }
            set
            {
                _ysTitle = value;
                RaisePropertyChanged(nameof(YsTitle));
            }
        }

        #endregion

        #region ceTitle

        private string _ceTitle;

        public string CeTitle
        {
            get { return _ceTitle; }
            set
            {
                _ceTitle = value;
                RaisePropertyChanged(nameof(CeTitle));
            }
        }

        #endregion


        #region LeftSet

        private ObservableCollection<IOrderItem> _LeftSet;

        public ObservableCollection<IOrderItem> LeftSet
        {
            get { return _LeftSet; }
            set
            {
                _LeftSet = value;
                1.UseUIThread(() => RaisePropertyChanged(nameof(LeftSet)));
            }
        }

        #endregion

        #region RightSet

        private ObservableCollection<IOrderItem> _RightSet;

        public ObservableCollection<IOrderItem> RightSet
        {
            get { return _RightSet; }
            set
            {
                _RightSet = value;
                 RaisePropertyChangedUI(nameof(RightSet) );
            }
        }

        #endregion


        #region IncludeFromProductionLine

        #region Cursorc

        private Cursor _Cursorc;

        public Cursor Cursorc
        {
            get { return _Cursorc; }
            set
            {
                _Cursorc = value;
                RaisePropertyChangedUI(nameof(Cursorc));
            }
        }

        #endregion

        private bool _includeFromProductionLine=true  ;

        public bool IncludeFromProductionLine
        {
            get { return _includeFromProductionLine; }
            set
            {
                _includeFromProductionLine = value;
                RaisePropertyChanged(nameof(IncludeFromProductionLine));
            }
        }

        #endregion


        void RunLongTask(Action action)
        {
            try
            {
                Biz = true;
                action?.Invoke();
            }
            finally
            {
                Biz = false;
            }
        }

        #region Biz

        private bool _Biz;

        public bool Biz
        {
            get { return _Biz; }
            set
            {
                _Biz = value;
                Cursorc = value ? Cursors.Wait : Cursors.Arrow;
                1.UseUIThread(() => RaisePropertyChanged(nameof(Biz)));
            }
        }

        #endregion

        void RaisePropertyChangedUI(string propertyName)
        {
            1.UseUIThread(() => RaisePropertyChanged(propertyName));
        }

        #region InCludeFromRegroup

        private bool _includeFromRegroup;
        private IAccountingVoucherManager _voucherManager;

        public bool IncludeFromRegroup
        {
            get { return _includeFromRegroup; }
            set
            {
                _includeFromRegroup = value;
                RaisePropertyChanged(nameof(IncludeFromRegroup));
            }
        }

        // public AccountPeriod Perio { get; set; } = new AccountPeriod();

        #region Perio

        private AccountPeriod _perio ;

        public AccountPeriod Perio
        {
            get { return _perio; }
            set
            {
                _perio = value;
                RaisePropertyChanged(nameof(Perio));
            }
        }

        #endregion
        
        public DelegateCommand CmdCheckAndCreateVouchers { get; set; }
        // public ObservableCollection<AccountVoucherVm> Vouchers { get; set; }=

        
        #endregion


        #region OnlyShowManualVouchers

        private bool _OnlyShowManualVouchers=true;

        public bool OnlyShowManualVouchers
        {
            get { return _OnlyShowManualVouchers; }
            set
            {
                _OnlyShowManualVouchers = value;
                RaisePropertyChanged(nameof(OnlyShowManualVouchers));

                var res= Vouchers
                    .Where(x => x.DO.VType != VType.系统生成 || !OnlyShowManualVouchers);
                VouchersManual = new ObservableCollection<AccountVoucherVm>(res);
            }
        }

        #endregion

        #region Vouchers

        private ObservableCollection<AccountVoucherVm> _vouchers=new ObservableCollection<AccountVoucherVm>();

        public ObservableCollection<AccountVoucherVm> Vouchers
        {
            get { return _vouchers; }
            set
            {
                _vouchers = value;
                RaisePropertyChangedUI(nameof(Vouchers));
                OnlyShowManualVouchers = OnlyShowManualVouchers;
            }
        }

        #endregion


        #region VouchersManual

        private  ObservableCollection<AccountVoucherVm> _VouchersManual;

        public  ObservableCollection<AccountVoucherVm> VouchersManual
        {
            get { return _VouchersManual; }
            set
            {
                _VouchersManual = value;
                RaisePropertyChangedUI(nameof(VouchersManual));
            }
        }

        #endregion
        

        //
        //
        // #region CurrentVoucher
        //
        // private AccountVoucherVm _CurrentVoucher;
        //
        // public AccountVoucherVm CurrentVoucher
        // {
        //     get { return _CurrentVoucher; }
        //     set
        //     {
        //         _CurrentVoucher = value;
        //         RaisePropertyChanged(nameof(CurrentVoucher));
        //     }
        // }
        //
        // #endregion

        public void TrShowPopVoucher()
        {

            if (_currentVoucher != null) ShowPopVoucher = true;
        }
    }
}